package com.eian.boot.rabbit.config;

import com.eian.boot.rabbit.RabbitHelper;
import com.eian.boot.rabbit.core.listener.ConsumerErrorHandler;
import com.eian.boot.rabbit.core.listener.MessageListener;
import com.eian.boot.rabbit.core.sender.ConfirmCallbackImpl;
import com.eian.boot.rabbit.core.sender.RabbitTemplateProxy;
import com.eian.boot.rabbit.core.sender.ReturnsCallbackImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;

@Slf4j
@AutoConfiguration(after = RabbitAutoConfiguration.class)
@ConditionalOnClass(RabbitTemplate.class)
@EnableConfigurationProperties(RabbitPropertiesExt.class)
@Import({MessageRecovererConfig.class})
public class RabbitMQAutoConfiguration {

    @Bean
    public MessageConverter jackson2JsonMessageConverter(ObjectMapper objectMapper) {
        Jackson2JsonMessageConverter converter = new Jackson2JsonMessageConverter(objectMapper);
        converter.setAlwaysConvertToInferredType(false);
        return converter;
    }

    @Bean
    @ConditionalOnBean(ConnectionFactory.class)
    public RabbitTemplateProxy rabbitTemplateProxy(
            ConnectionFactory connectionFactory,
            MessageConverter messageConverter,
            RabbitPropertiesExt properties) {

        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        template.setMessageConverter(messageConverter);
        template.setMandatory(properties.returns());

        if ("correlated".equalsIgnoreCase(properties.confirmType())) {
            template.setConfirmCallback(new ConfirmCallbackImpl());
        }

        if (properties.returns()) {
            template.setReturnsCallback(new ReturnsCallbackImpl());
        }

        return new RabbitTemplateProxy(template, properties);
    }

    @Bean
    @ConditionalOnBean(ConnectionFactory.class)
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
            ConnectionFactory connectionFactory,
            MessageConverter messageConverter,
            ConsumerErrorHandler errorHandler) {

        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setMessageConverter(messageConverter);
        factory.setErrorHandler(errorHandler);
        return factory;
    }

    @Bean
    public RabbitHelper rabbitHelper(RabbitTemplateProxy rabbitTemplateProxy) {
        log.info("RabbitMQ初始化完成");
        return new RabbitHelper(rabbitTemplateProxy);
    }

    @Bean
    public MessageListener messageListener() {
        return new MessageListener();
    }
}